package main

import (
	"math/rand"
	"sync/atomic"
	"time"
	"fmt"
)

//使用goroutines和通道的内置同步功能来实现相同的结果
type readOps struct {
	key  int
	resp chan int
}

type writeOps struct {
	key  int
	val  int
	resp chan bool
}

func main() {
	var readOp uint64
	var writeOp uint64

	//在reads和writes渠道将被其它够程可分别用于发出读取和写入请求
	reads := make(chan *readOps)
	writes := make(chan *writeOps)

	//这是拥有它的goroutine state,但现在对于有状态的goroutine是私有的
	//这个goroutine重复选择reads和writes通道，在他们到达时回应请求
	//通过首先执行所请求的操作并且然后在响应通道上发送值resp以指示成功（以及在该情况下的期望值）来执行响应reads
	go func() {
		var state = make(map[int]int)
		for {
			select {
			case r := <-reads:
				r.resp <- state[r.key]
			case w := <-writes:
				state[w.key] = w.val
				w.resp <- true
			}
		}
	}()

	//这启动了100个线程来通过该reads通道向州拥有的goroutine发出读取
	//每次读取需要构建一个readOp，通过reads频道发送，并通过提供的resp频道接收结果
	for r := 0; r < 100; r++ {
		go func() {
			for {
				read := &readOps{key: rand.Intn(5), resp: make(chan int)}
				reads <- read
				<-read.resp
				atomic.AddUint64(&readOp, 1)
				time.Sleep(time.Millisecond)
			}
		}()
	}

	//类似读
	for w := 0; w < 10; w++ {
		go func() {
			for {
				write := &writeOps{key: rand.Intn(5), val: rand.Intn(100), resp: make(chan bool)}
				writes <- write
				<-write.resp
				atomic.AddUint64(&writeOp, 1)
				time.Sleep(time.Millisecond)
			}
		}()
	}

	time.Sleep(time.Second)
	readOpsFinal := atomic.LoadUint64(&readOp)
	fmt.Println("read:", readOpsFinal)
	writeOpsFinal := atomic.LoadUint64(&writeOp)
	fmt.Println("write:", writeOpsFinal)
}
